#include <gnss_power_mgr.h>
#include "gnss_request.h"
#include <qlcommon.h>
#include "gnss_log.h"

static struct list_head gnssmgr_req_list = LIST_HEAD_INIT(gnssmgr_req_list);

enum {
    GNSSMGR_REQ_BUSY,               /* 请求执行中 */
    GNSSMGR_REQ_ERROR,              /* 请求执行错误 */
    GNSSMGR_REQ_END                 /* 请求执行完成 */
};

typedef struct {
    uint8_t     stage;
    uint32_t    uptime;
    void*       param;
} req_cps_t;

typedef struct {
    uint8_t             req_id;     /* 请求ID */
    gnss_req_callback   cb;         /* 请求回调函数 */
    req_cps_t           cps;        /* 请求管理参数 */
    struct list_head    list;
} gnssmgr_req_list_t;

/**
 * @brief GNSS 请求是否为空
 * @return true - 空, false - 非空
 */
bool gnssmgr_request_is_empty(void)
{
    return list_empty(&gnssmgr_req_list) ? true : false;
}

/**
 * @brief GNSS 请求注册
 * @param id 请求ID
 * @param cb 请求完成后的回调函数
 * @return 0 - 发送成功, 负数 - 错误码
 */
int32_t gnssmgr_request_register(uint8_t id, gnss_req_callback cb)
{
    gnssmgr_req_list_t *node = NULL;

    node = qlmalloc(sizeof(gnssmgr_req_list_t));
    if (NULL == node)
        return -ENOMEM;
    memset(node, 0, sizeof(gnssmgr_req_list_t));

    node->req_id    = id;
    node->cb        = cb;

    gnssmgrSemaphoreTake();
    list_add_tail(&(node->list), &gnssmgr_req_list);
    gnssmgrSemaphoreGive();

    return 0;
}

/**
 * @brief GNSS 请求删除
 * @param node 请求节点
 */
static void gnssmgr_request_delete(gnssmgr_req_list_t *node)
{
    if (NULL != node) {
        gnssmgrSemaphoreTake();
        list_del(&(node->list));
        gnssmgrSemaphoreGive();

        qlfree(node);
    }
}

/**
 * @brief GNSS 定位获取请求执行函数
 * @param cps 请求管理参数
 * @param gnss_req_cb 请求完成后的回调函数
 * @return 详情看枚举定义
 */
static int32_t gnssmgr_fix_request_handler(req_cps_t *cps, gnss_req_callback callback)
{
    struct fix_info info = {0};
    
    switch (cps->stage) {
    case 0:
        if (FIX_OK == is_gnss_fixed(NULL))
            goto done;
        cps->uptime = getsec();
        cps->stage++;
        break;

    case 1:
        if (timeout_sec(cps->uptime, GNSS_FIX_TIMEOUT_DEFAULT) || FIX_OK == is_gnss_fixed(NULL))
            goto done;
        break;

    default:
        return GNSSMGR_REQ_ERROR;
    }

    return GNSSMGR_REQ_BUSY;

done:
    get_last_gnss_info(&info);
    /* 执行回调函数 */
    if (NULL != callback)
        callback(&info, sizeof(struct fix_info));
    gnss_trace(LOG_INFO "Request gnss open end,and current fix info already get\r\n");
    return GNSSMGR_REQ_END;

}

typedef int32_t (*request_impl)(req_cps_t *cps, gnss_req_callback cb);

typedef struct {
    uint8_t         req_id;
    request_impl    impl;
} gnssmgr_request_impl;

/* 请求实现函数列表(注意不能在实现函数中使用静态或者全局变量, 功能尽量单一) */
static gnssmgr_request_impl request_impl_table[] = {
    {GNSSMGR_FIX_REQUEST, gnssmgr_fix_request_handler},
};

/**
 * @brief GNSS 请求执行函数
 */
void gnssmgr_request_handler(void)
{
    struct list_head *list_ptr,*n = NULL;
    gnssmgr_req_list_t *node = NULL;
    int32_t result = GNSSMGR_REQ_BUSY;
    
    if (list_empty(&gnssmgr_req_list))
        return;

    list_for_each_safe(list_ptr, n, &gnssmgr_req_list) {
        node = list_entry(list_ptr, gnssmgr_req_list_t, list);
        for (int32_t i = 0; i < ARRAY_COUNT(request_impl_table); i++) {
            if (node->req_id == request_impl_table[i].req_id) {
                result = request_impl_table[i].impl(&node->cps, node->cb);
                break;
            }
        }

        /* 判断当前请求执行结果 */
        if (GNSSMGR_REQ_BUSY == result) {
            continue;
        }
        else {
            gnss_trace(LOG_INFO "gnss request id: %d exec end\r\n", node->req_id);
            /* 请求执行结束需要清除节点 */
            gnssmgr_request_delete(node);
        }
        return;
    }
}

